package network.tpb;

import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import network.AbstractNetworkInterface;
import network.AbstractUserSignal;
import network.ListenerBindException;
import network.config.NetworkConfiguration;
import network.SendSignalException;

import user.LocalUser;
import controller.MessageController;
import controller.UserNotConnected;

import itdb1.commun.*;

public class NetworkInterfaceB extends AbstractNetworkInterface {
	
	private String createLocalUserName () {
		return LocalUser.getLocalUser().getUsername() ;
	}
	
	public void sendHello (String username) throws SendSignalException {
		super.sender.sendSignal(new UserSignalB(new Hello(username), null)) ;
	}
	
	public void sendHelloReply (String username, InetAddress remoteAddress) throws SendSignalException {
		super.sender.sendSignal(new UserSignalB(new HelloAck(createLocalUserName()), remoteAddress)) ;
	}
	
	public void sendGoodBye () throws SendSignalException {
		super.sender.sendSignal(new UserSignalB(new Bye (), null)) ;
	}
	
	public void sendAskLogin (InetAddress to) throws SendSignalException {
		super.sender.sendSignal(new UserSignalB(new Hello(createLocalUserName()), to)) ;
	}
	
	public void sendMessage (String message, InetAddress to, InetAddress[] cc) throws SendSignalException {
		super.sender.sendSignal(new UserSignalB(new Message(message), to)) ;
	}
	
	public void sendPropFile (String filename, long fileSize, int fileID, InetAddress to) throws SendSignalException {
		throw new SendSignalException("Transfer file not supported.") ;
	}
	
	public void sendAcceptFile(InetAddress to, int fileID, boolean accepted, boolean now) throws SendSignalException {
		throw new SendSignalException("Transfer file not supported.") ;
	}
	
	private HeartBeater heartBeater ;
	
	/**
	 * Create a new NetworkInterface connected with the specified MessageController
	 * 
	 * @param msgCtrl
	 * @throws ListenerBindException if an error occurs starting the udp listener thread
	 */
	public NetworkInterfaceB (MessageController msgCtrl, NetworkConfiguration nc) throws ListenerBindException {
		super (msgCtrl, nc) ;
		try {
			this.heartBeater = new HeartBeater(nc) ;
		}
		catch (SocketException e) {
			throw new ListenerBindException(e) ;
		}
	}
	
	@Override
	public void start () {
		this.heartBeater.start() ;
		super.start();
	}
	
	@Override
	public synchronized void finish () {
		this.heartBeater.finish() ;
		synchronized (this.heartBeater) {
			this.heartBeater.notify() ;
		}
		super.finish () ;
	}
	

	@Override
	protected void addSignal(DatagramPacket packet) {
		addAbstractSignal(new UserSignalB(packet)) ;
	}
	
	/**
	 * Perform action corresponding to the specified signal using
	 * the message controller.
	 * 
	 * @param si
	 * @throws UserNotConnected 
	 * @throws SendSignalException 
	 * @throws UnknownHostException 
	 */
	protected void performSignal (AbstractUserSignal aus) throws UnknownHostException, SendSignalException, UserNotConnected {
		UserSignalB usi = (UserSignalB)aus ;
		InetAddress addr = usi.getAddress() ;
		NetworkSignal si = usi.getSignal() ;
		if (si instanceof Hello) {
			Hello he = (Hello)si ;
			super.msgCtrl.processHello (he.getUsername(), addr) ;
		}
		else if (si instanceof HelloAck) {
			System.out.println("Hello Ack") ;
			HelloAck hea = (HelloAck)si ;
			super.msgCtrl.processHelloReply (hea.getUsername(), addr) ;
		}
		else if (si instanceof Bye) {
			super.msgCtrl.processGoodBye(addr) ;
		}
		else if (si instanceof Message) {
			Message msg = (Message)si ;
			super.msgCtrl.processSendText(msg.getMessage(), new InetAddress[] { LocalUser.getLocalUser().getAddress()  }, addr) ;
		}
		else if (si instanceof HeartBeats) {
			HeartBeats hb = (HeartBeats)si ;
			super.msgCtrl.processHelloReply(hb.getUsername(), addr) ;
		}
	}
	
}
